﻿#region Copyright

// All Material Copyright © 2010 Dynamic Concepts Development Corp., All Rights Reserved.
//      Portions Copyright © 1984-2009 Dynamic Concepts Development Corp., All Rights Reserved.
// For further information please contact: SoftwareSupport@dynconcepts.com
// Dynamic Concepts Development Corp.  311 W 57th St. Suite #422, New York, NY 10019

#endregion

#region Using References

using System;
using System.IO;
using System.Text;
using DynConDevCorp.OpenArch.SupportLibrary.Serialization;

#endregion

namespace DynConDevCorp.OpenArch.DynAppFramework.Tiers.UserInterface.WPF.Engine
{
    public static class ViewModelPersistance
    {
        #region Public Methods

        public static ViewModelItemBase LoadModel(Stream stream)
        {
            ViewModelItemBase viewModel = null;
            using (StreamReader reader = new StreamReader(stream))
            {
                string line;
                line = reader.ReadLine(); // ("<ViewModel>");
                line = reader.ReadLine(); // "<PersistenceVersion>{0}</PersistenceVersion>", typeof(ViewModelPersistance).AssemblyQualifiedName);
                line = reader.ReadLine(); // "<ViewModelVersion>{0}</ViewModelVersion>", viewModel.GetType().AssemblyQualifiedName);
                int start = line.IndexOf("<ViewModelVersion>") + "<ViewModelVersion>".Length;
                int end = line.IndexOf("</ViewModelVersion>");
                string modelTypeName = line.Substring(start, end - start);
                Type modelType = Type.GetType(modelTypeName);
                if (modelType == null)
                {
                    throw new Exception(String.Format("Could not find Type: {0}", modelTypeName));
                }
                line = reader.ReadLine(); // ("<Content>");
                string buffer = reader.ReadToEnd();
                viewModel = DeSerialize(modelType, buffer);
                line = reader.ReadLine(); // ("</Content>");
                line = reader.ReadLine(); // "</ViewModel>");
            }
            return viewModel;
        }

        public static ViewModelItemBase LoadModelFromFile(String fileName)
        {
            try
            {
                using (Stream inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    return LoadModel(inputStream);
                }
            }
            catch (Exception)
            {
                return null;
            }
        }


        public static void SaveModel(Stream stream, ViewModelItemBase viewModel)
        {
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.WriteLine("<ViewModel>");
                writer.WriteLine("<PersistenceVersion>{0}</PersistenceVersion>", typeof (ViewModelPersistance).AssemblyQualifiedName);
                writer.WriteLine("<ViewModelVersion>{0}</ViewModelVersion>", viewModel.GetType().AssemblyQualifiedName);
                writer.WriteLine("<Content>");
                writer.WriteLine("{0}", Serialize(viewModel));
                writer.WriteLine("</Content>");
                writer.WriteLine("</ViewModel>");
            }
        }

        public static void SaveModelToFile(String fileName, ViewModelItemBase viewModel)
        {
            using (Stream outputStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                SaveModel(outputStream, viewModel);
            }
        }

        #endregion

        #region Private Methods

        private static ViewModelItemBase DeSerialize(Type viewModelType, string src)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] byteArray = encoding.GetBytes(src);
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(byteArray, 0, byteArray.Length);
                stream.Seek(0, SeekOrigin.Begin);
                StreamReader reader = new StreamReader(stream);
                CustomObjectSerializer serializer = GetSerializer(viewModelType);
                ViewModelItemBase result = (ViewModelItemBase) serializer.Deserialize(reader, viewModelType);
                return result;
            }
        }

        private static CustomObjectSerializer GetSerializer(Type viewModelType)
        {
            CustomObjectSerializer serializer = new CustomObjectSerializer(viewModelType);
            return serializer;
        }

        private static string Serialize(ViewModelItemBase viewModel)
        {
            CustomObjectSerializer serializer = GetSerializer(viewModel.GetType());
            MemoryStream stream = new MemoryStream();
            byte[] buffer;
            int len;
            using (StreamWriter writer = new StreamWriter(stream))
            {
                serializer.Serialize(writer, viewModel);
                writer.Flush();
                stream.Seek(0, SeekOrigin.Begin);
                len = (int) stream.Length;
                buffer = new byte[len];
                stream.Read(buffer, 0, len);
            }
            UTF8Encoding encoding = new UTF8Encoding();
            char[] charArray = new char[encoding.GetCharCount(buffer, 0, len)];
            encoding.GetDecoder().GetChars(buffer, 0, len, charArray, 0);
            string result = new string(charArray);
            return result;
        }

        #endregion
    }
}